package com.tarena.test.lbs.es;

import com.alibaba.fastjson2.JSON;
import com.tarena.test.lbs.es.builder.IndexBuilder;
import com.tarena.test.lbs.es.pojo.Student;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequestBuilder;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

public class ESSearchTestRun {
    private RestHighLevelClient client;
    @Before
    public void initClient(){
        HttpHost httpHost=new HttpHost("localhost",9200,"http");
        RestClientBuilder builder= RestClient.builder(httpHost);
        client=new RestHighLevelClient(builder);
    }

    @Test
    public void initData() throws Exception{
        IndexBuilder.buildData("students",100);
    }

    @Test
    public void searchAll() throws IOException{
        //1.构造一个查询搜索条件的对象
        SearchRequest request = new SearchRequest("students");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //1.1 查询条件
        MatchAllQueryBuilder matchAll = QueryBuilders.matchAllQuery();
        searchSourceBuilder.query(matchAll);
        //1.2 分页查询
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(100);
        // 设置排序负责
        searchSourceBuilder.sort("birthday", SortOrder.DESC);
        // 聚合 统计
        request.source(searchSourceBuilder);
        //2 执行请求 用ES查询
        SearchResponse searchResponse =
                client.search(request, RequestOptions.DEFAULT);
        //2.1解析查询结果、总数
        TotalHits totalHits = searchResponse.getHits().getTotalHits();
        System.out.println("总数:"+totalHits.value);
        //2.2 查询返回数据结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            //打印获取所有的文档信息
            hit.getIndex();
            hit.getId();
            System.out.println(JSON.parseObject(hit.getSourceAsString(), Student.class));
        }
    }

    //Termquery 全文检索查询的计算
    //ES 部分查询 -->IK
    //查询到的结果用 IK分词器进行拆分
    @Test
    public void searchByTerm() throws IOException {
        SearchRequest request = new SearchRequest("students");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //1.查询条件 name 对应查询 doc字段属性名字
        TermQueryBuilder query =
                QueryBuilders.termQuery("name","强");
        //2.封装,执行请求
        builder.query(query);
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println("总数:"+response.getHits().getTotalHits().value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            //打印获取所有的文档信息
            hit.getIndex();
            hit.getId();
            System.out.println(JSON.parseObject(hit.getSourceAsString(), Student.class));
        }
    }

    //matchQuery 传递参数 依然是一个属性名字 和一个文本 文本不当成term,进行分词计算
    //matchQuery 把Query的条件可以用分词器进行拆分
    @Test
    public void searchByMatch() throws IOException{
        SearchRequest request = new SearchRequest("students");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //1.查询条件
        MatchQueryBuilder query = QueryBuilders
                .matchQuery("name","王小王猎杀");
        //2.封装查询条件
        builder.query(query);
        builder.from(0);
        builder.size(100);
        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println("总数:"+response.getHits().getTotalHits().value);
        SearchHit[] hits = response.getHits().getHits();
        if (hits!=null && hits.length>0){
            for (SearchHit hit : hits) {
                System.out.println(JSON.parseObject(hit.getSourceAsString(),
                        Student.class));
            }
        }
    }

    //搜索地理位置的范围中心点是 39.9072 116.4074
    @Test
    public void searchByDistance() throws IOException{
        SearchRequest request = new SearchRequest("students");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //1.查询条件
        //1.1设置一个中心点
        GeoPoint geoPoint = new GeoPoint(39.9072, 116.4074);
        GeoDistanceQueryBuilder query = QueryBuilders.geoDistanceQuery("location");
        query.point(geoPoint).distance(500.0,DistanceUnit.KILOMETERS);
        //2.封装,执行请求
        builder.query(query);
        builder.from(0);
        builder.size(100);
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println("总数:"+response.getHits().getTotalHits().value);
        //打印结果
        SearchHit[] hits = response.getHits().getHits();
        if (hits!=null&&hits.length>0){
            for (SearchHit hit : hits) {
                System.out.println(JSON.parseObject(hit.getSourceAsString(),
                        Student.class));
            }
        }

    }

    //BooleanQuery(多条件组合查询)
    @Test
    public void searchByBoolean() throws Exception{
        SearchRequest request = new SearchRequest("students");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //1.设置查询条件
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        //1.1设置名称匹配(字段匹配 -- IK)
        MatchQueryBuilder boolQuery1 = QueryBuilders.matchQuery("name", "王小王");
        //1.2设置时间匹配(范围匹配 --Range)
        RangeQueryBuilder boolQuery2 = QueryBuilders.rangeQuery("birthday");
        boolQuery2.gt("2005-01-01").lt("2011-12-31");
        //1.3设置位置匹配
        GeoPoint geoPoint = new GeoPoint(39.9072, 116.4074);
        GeoDistanceQueryBuilder GeoQuery = QueryBuilders.geoDistanceQuery("location");
        //设置半径和单位
        GeoQuery.point(geoPoint).distance(500.0, DistanceUnit.KILOMETERS);

        query.must(boolQuery1);
        query.must(boolQuery2);
        query.must(GeoQuery);

        //2.封装执行请求,打印返回结果
        builder.query(query);
        builder.from(0);
        builder.size(100);
        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println("总数:"+response.getHits().getTotalHits().value);
        SearchHit[] hits = response.getHits().getHits();
        if (hits!=null && hits.length>0){
            for (SearchHit hit : hits) {
                System.out.println(JSON.parseObject(hit.getSourceAsString(),
                        Student.class));
            }
        }


    }
}
